﻿using System;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Pool;

namespace EchoFramework
{
    /// <summary>
    /// 时间管理器
    /// </summary>
    public class TimeManager : Singleton<TimeManager>
    {
        /// <summary>
        /// 自从游戏启动到现在的帧数
        /// 依据Update
        /// </summary>
        public static int FrameSinceGameStart;

        /// <summary>
        /// 自从游戏启动到现在的时间(单位：秒)
        /// </summary>
        public static float TimeSeconedFloat;

        /// <summary>
        /// 自从游戏启动到现在的时间(单位：秒)
        /// </summary>
        private static int TimeSeconedInt;

        /// <summary>
        /// Dispatcher对象池
        /// </summary>
        private ObjectPool<Dispatcher> dispatcherPool;

        /// <summary>
        /// 已记录的Dispatcher对象列表
        /// </summary>
        private List<Dispatcher> dispatcherList;

        public override void OnAwake()
        {
            base.OnAwake();
            dispatcherList = new List<Dispatcher>();
        }

        public override void OnStart(Action action = null)
        {
            base.OnStart(action);
            InitDispatcherPool();  //初始化Dispatcher对象池
        }
        
        public override void OnUpdate()
        {
            base.OnUpdate();
            FrameSinceGameStart++;
            TimeSeconedFloat += Time.deltaTime;
            TimeSeconedInt = (int) TimeSeconedFloat;

            CheckDispatcher();  //遍历检测已记录的Dispatcher列表
        }
        
        

        /// <summary>
        /// 初始化Dispatcher对象池
        /// </summary>
        private void InitDispatcherPool()
        {
            //创建
            Func<Dispatcher> createFunc = () => { return new Dispatcher(); };
            //释放
            Action<Dispatcher> actionOnRelease = dispatcher => { dispatcher.Reset(); };
            dispatcherPool = new ObjectPool<Dispatcher>(createFunc, null, actionOnRelease);
        }


        /// <summary>
        /// 检测Dispatcher对象列表，满足条件则执行其行为
        /// </summary>
        private void CheckDispatcher()
        {
            for (int i = dispatcherList.Count; i > 0 ; i--)
            {
                Dispatcher tempDispatcher = dispatcherList[i - 1];
                if (tempDispatcher.CheckExecute())
                {
                    dispatcherList.Remove(tempDispatcher);
                    dispatcherPool.Release(tempDispatcher);
                }
            }
        }

        /// <summary>
        /// 主动释放Dispatcher
        /// </summary>
        /// <param name="dispatcher">指定的Dispatcher对象</param>
        public void DisposeDispatcher(Dispatcher dispatcher)
        {
            dispatcher?.Reset();
        }
        
        /// <summary>
        /// 延迟时间调用(单位：秒)
        /// </summary>
        /// <param name="delayTime">延迟多少时间</param>
        /// <param name="action">行为</param>
        /// <returns>返回Dispatcher对象</returns>
        public Dispatcher DelaySeconed(float delayTime, Action action)
        {
            Dispatcher dispatcher = dispatcherPool.Get();
            dispatcher.Init(global::Dispatcher.Time, action, delayTime, 0);
            dispatcherList.Add(dispatcher);
            return dispatcher;
        }
        
        /// <summary>
        /// 延迟1秒后调用
        /// </summary>
        /// <param name="action">行为</param>
        /// <returns>返回Dispatcher对象</returns>
        public Dispatcher DelayOneSeconed(Action action)
        {
            Dispatcher dispatcher = DelaySeconed(1f, action);
            return dispatcher;
        }
        
        /// <summary>
        /// 延迟帧数调用(单位：帧)
        /// </summary>
        /// <param name="delayFrame">延迟多少帧数</param>
        /// <param name="action">行为</param>
        /// <returns>返回Dispatcher对象</returns>
        public Dispatcher DelayFrame(int delayFrame, Action action)
        {
            Dispatcher dispatcher = dispatcherPool.Get();
            dispatcher.Init(global::Dispatcher.Frame, action, 0, delayFrame);
            dispatcherList.Add(dispatcher);
            return dispatcher;
        }
        
        /// <summary>
        /// 延迟1帧后调用
        /// </summary>
        /// <param name="action">行为</param>
        /// <returns>返回Dispatcher对象</returns>
        public Dispatcher DelayOneFrame(Action action)
        {
            Dispatcher dispatcher = DelayFrame(1, action);
            return dispatcher;
        }
    }
}